local function updateHorizontalScrollBar(self)
    self._horizontalScrollBar.scrollValue = self._scrollContent.dragPercentX
end

local function updateVerticalScrollBar(self)
    self._verticalScrollBar.scrollValue = self._scrollContent.dragPercentY
end

local function onVerticalScrollBar(self, val)
    self._scrollContent.dragPercentY = val
end

local function onHorizontalScrollBar(self, val)
    self._scrollContent.dragPercentX = val
end
local function bindHorizontalScrollBar(self)
    self._horizontalScrollBar:on(ScrollBarEvent.ValueChanged, onHorizontalScrollBar, self)
    self._scrollContent:on(NodeEvent.OnDragMoved, updateHorizontalScrollBar, self)
end

local function bindVerticalScrollBar(self)
    self._verticalScrollBar:on(ScrollBarEvent.ValueChanged, onVerticalScrollBar, self)
    self._scrollContent:on(NodeEvent.OnDragMoved, updateVerticalScrollBar, self)
end
ScrollView = {
    props = {
        _horizontalScrollable = true,
        _verticalScrollable = true,
    },
    gets = {
        horizontalScrollable = function (self)
            return self._horizontalScrollable
        end,
        verticalScrollable = function (self)
            return self._verticalScrollable
        end,
        scrollContent = function (self)
            return self._scrollContent
        end,
        horizontalScrollBar = function (self)
            return self._horizontalScrollBar
        end,
        verticalScrollBar = function (self)
            return self._verticalScrollBar
        end,
    },
    sets = {
        horizontalScrollable = function (self, key, val)
            self._horizontalScrollable = val
            self:_updateScrollContentDragable()
        end,
        verticalScrollable = function (self, key, val)
            self._verticalScrollable = val
            self:_updateScrollContentDragable()
        end,
        scrollContent = function (self, key, val)
            if self._scrollContent == val then
                return
            end
            self._scrollContent = val
            val.dragLimitMode = DragLimitMode.ContainParent
            self:_updateScrollContentDragable()
        end,
        horizontalScrollBar = function (self, key, val)
            self._horizontalScrollBar = val
            bindHorizontalScrollBar(self)
        end,
        verticalScrollBar = function (self, key, val)
            self._verticalScrollBar = val
            bindVerticalScrollBar(self)
        end,
    }
}

function ScrollView:_updateScrollContentDragable()
    self._scrollContent.xdraggable = self._horizontalScrollable
    self._scrollContent.ydraggable = self._verticalScrollable
end

function Node.ScrollView(args)
    local width = args and args.width and args.width or 200
    local height = args and args.height and args.height or 200
    local scrollView = Node.new():wh(width, height)
    if args and args.backgroundColor then
        scrollView:addComponent(Sprite)
        scrollView.color = args.backgroundColor
    end
    scrollView:addComponent(ScrollView)
    local viewPort = Node.new():addTo(scrollView)
    viewPort.name = "viewPort"
    viewPort:addComponent(Scissor)
    viewPort:addComponent(Stretch)
    viewPort:addComponent(Align)
    scrollView.viewPort = viewPort

    local content = Node.new():addTo(viewPort)
    content.name = "scrollContent"
    content:addComponent(Drag)
    content.ignoreChildBlock = true
    content:wh(300, 300)
    scrollView.scrollContent = content

    if args and args.scrollBar then
        local hBar = Node.ScrollBar({
            direction = ScrollBarDirection.LeftToRight
            })
        hBar:addTo(scrollView)
        hBar:addComponent(Align)
        hBar:addComponent(Stretch)
        hBar.alignPercentY = 1
        hBar.alignOffsetY = -10
        hBar.stretchOffsetX = -20
        hBar.stretchType = StretchType.Horizontal
        hBar.alignOffsetX = -10
        scrollView.horizontalScrollBar = hBar

        local vBar = Node.ScrollBar({
            direction = ScrollBarDirection.TopToBottom
            })
        vBar:addTo(scrollView)
        vBar:addComponent(Align)
        vBar:addComponent(Stretch)
        vBar.alignPercentX = 1
        vBar.alignOffsetX = -10
        vBar.stretchType = StretchType.Vertical
        vBar.alignOffsetY = -10
        vBar.stretchOffsetY = -20
        scrollView.verticalScrollBar = vBar

        viewPort.stretchOffsetX = -20
        viewPort.stretchOffsetY = -20
        viewPort.alignOffsetX = -10
        viewPort.alignOffsetY = -10
    end
    return scrollView
end

function Node.ScrollListVertical(pool)
    local scrollView = Node.ScrollView()
    scrollView.scrollContent:addComponent(Layout)
    scrollView.scrollContent.layoutSizeMode = LayoutSizeMode.StretchY
    scrollView.scrollContent:addComponent(Stretch, {stretchType = StretchType.Horizontal})
    local list = Node.List(pool)
    list.layoutSizeMode = LayoutSizeMode.StretchY
    list:addComponent(Stretch, {stretchType = StretchType.Horizontal})
    list:addTo(scrollView.scrollContent)
    -- list:axy(0, 0)
    -- list.alignPercentX = 0
    -- list.alignPercentY = 0
    scrollView.list = list

    return scrollView
end

function Node.ScrollList(pool)
    local scrollView = Node.ScrollView()
    scrollView.scrollContent:addComponent(Layout)
    scrollView.scrollContent.layoutSizeMode = LayoutSizeMode.Stretch

    local list = Node.List(pool)
    list.name = "ScrollList"
    list:addTo(scrollView.scrollContent)
    scrollView.list = list

    return scrollView
end